/*
* Author:  Greg Nowak and Vaibhav Sharma
* Michigan State University
* 
* This is the implementation of the NFC Wireless Sensor Network Application
*/
#include "Timer.h"  /* For timer control */
#include "printf.h"
#include "NFCWireless.h"
#include "Msp430Adc12.h"
#include "mutex.h"


module NFCWirelessC
{
  	uses interface Timer<TMilli> as Timer0;  /* Reads temperature, logs to flash */
  	uses interface Timer<TMilli> as Timer1;  /* Sends all data in flash */
  	uses interface Timer<TMilli> as ReceiveTimer;  /* Sends all data in flash */
  	uses interface Timer<TMilli> as ProbeTimer;  /* Sends all data in flash */
  	uses interface Timer<TMilli> as WaitTimer;  /* Sends all data in flash */
  	uses interface LocalTime<TMilli>;
 	uses interface Leds;
  	uses interface Boot;
	uses interface LogRead;
	uses interface LogWrite;
	uses interface Read<uint16_t> as TemperatureReading;
	uses interface Read<uint16_t> as BatteryVoltage;
    uses interface Packet;
    uses interface AMPacket;
    uses interface AMSend;
    uses interface Receive;
    uses interface SplitControl as AMControl;
    uses interface HplMsp430GeneralIO as EnergyHarvesterDiscrete;
  provides interface AdcConfigure<const msp430adc12_channel_config_t*> as ACD_A4_Configure;
}
implementation
{
  uint8_t state = IDLE;
  norace uint16_t packetReceivedCount[4] = {0};
  uint16_t totalPacketSentCount = 0;
  /***  Module Variables Start ************************************/
  bool mModuleSleeping = FALSE;
  /* Packet Writing Variables */
  uint16_t packetCountWritten = 0;
  uint16_t packetCountRead = 0;
  uint16_t packetSentCount = 0;
  uint8_t mProbesSent = 0;
  bool mRCVWindow = FALSE; 
  
  /* Timer Variables */
  uint32_t mStart_time;
  uint32_t mStop_time;
  uint32_t mTemperatureTimeStamp;
  uint32_t mDesiredSleepSchedule = SHORT_SLEEP_SCHEDULE_MILI; /* Default to short sleep cycle */
  
  /* Data logging variables */
	typedef nx_struct flashLogEntry_t 
	{
    	nx_uint32_t timeStamp;
    	nx_uint16_t temperature;
		//nx_uint8_t voltage;
		nx_float voltage;
    	nx_uint8_t srcNodeID;
    	nx_uint8_t sentStatus;
        nx_uint8_t probe;
        nx_uint8_t hopCount;
        nx_uint8_t dstNodeID;
  	} flashLogEntry_t;
    flashLogEntry_t mRemoteBufferedEntries[MAX_BUFFERED_ENTRIES];
    int16_t mRemoteBufferedEntriesIndex=0;

  	norace bool mLogBusy = FALSE;  	
    flashLogEntry_t mLocalEntry;
    flashLogEntry_t mRemoteEntry;
  
  /*  Temperature sensing variables */
  uint16_t mTemperatureReading = 0;
  bool mReadBusy = FALSE;
  
  /*  Packet sending variables */
  flashLogEntry_t mLocalLogEntry;
  flashLogEntry_t mLocalProbePkt;
  uint8_t dstNodeID;
  bool mSendBusy = FALSE;
  uint32_t mSendPacketsStartTime;
  uint32_t mSendPacketsEndTime;
  bool radioBusy = FALSE;
  bool sychnronizeSleepSchedule = FALSE;
  message_t pkt;
  void WakeUp();
  void GoToSleep();
  /* Used to print a float via printf */
  void printfFloat(float toBePrinted) {
     uint32_t fi, f0, f1, f2;
     char c;
     float f = toBePrinted;

     if (f<0){
       c = '-'; f = -f;
     } else {
       c = ' ';
     }

     // integer portion.
     fi = (uint32_t) f;

     // decimal portion...get index for up to 3 decimal places.
     f = f - ((float) fi);
     f0 = f*10;   f0 %= 10;
     f1 = f*100;  f1 %= 10;
     f2 = f*1000; f2 %= 10;
     printf("%c%ld.%d%d%d", c, fi, (uint8_t) f0, (uint8_t) f1,  
		(uint8_t) f2);
   }
   
   float mLastVoltageRead;
   task void determineDesiredSleepSchedule()
   {
   
   		/* We are in the largest battery voltage, so we want to set the sleep schedule
   		 * to be the shortest duration (i.e. sleep the least since we have the battery anyway 
   		 */ 		   		 
   		if( mLastVoltageRead > (MAX_BATTERY_VOLTAGE - LARGE_SLEEP_SCHEDULE_WIDTH))
   		{
   			call Leds.led0On();
   			call Leds.led1Off();
   			call Leds.led2Off();
   			mDesiredSleepSchedule = SHORT_SLEEP_SCHEDULE_MILI;
		}else if( mLastVoltageRead > (MAX_BATTERY_VOLTAGE - LARGE_SLEEP_SCHEDULE_WIDTH - SMALL_SLEEP_SCHEDULE_WIDTH))
		{
   			call Leds.led0Off();
   			call Leds.led1On();
   			call Leds.led2Off();
			mDesiredSleepSchedule = MEDIUM_SLEEP_SCHEDULE_MILI;
		}else{
   			call Leds.led0Off();
   			call Leds.led1Off();
   			call Leds.led2On();
			mDesiredSleepSchedule = LONG_SLEEP_SCHEDULE_MILI;
		}
   	
   }
  	/**
	 * When the ADC Value is done reading, print the result
	 */
	event void BatteryVoltage.readDone(error_t result, uint16_t val){
		
		if ( result == SUCCESS)
		{
			/* Print the value */
			float value = ((float)val * ADC_REFERENCE_VOLTAGE)/MAX_ADC_COUNT;
			mLastVoltageRead = value;
			post determineDesiredSleepSchedule();
		}
	}
	
	/* Configuration necessary to do ADC convertion */
	  const msp430adc12_channel_config_t config = {
	      inch: INPUT_CHANNEL_A3,
	      sref: REFERENCE_VREFplus_AVss,
	      ref2_5v: REFVOLT_LEVEL_1_5,
	      adc12ssel: SHT_SOURCE_ACLK,
	      adc12div: SHT_CLOCK_DIV_1,
	      sht: SAMPLE_HOLD_4_CYCLES,
	      sampcon_ssel: SAMPCON_SOURCE_SMCLK,
	      sampcon_id: SAMPCON_CLOCK_DIV_1
	  };
	  /* Command needed to provide the configuration file */
	  async command const msp430adc12_channel_config_t* ACD_A4_Configure.getConfiguration()
	  {
	    return &config;
	  }
  /*******************************************************/
  /* This is the code that is called when the system starts.*/
  event void Boot.booted()
  {
     mModuleSleeping = TRUE;
	call EnergyHarvesterDiscrete.makeOutput();
    call Timer0.startPeriodic( 3333);
    call Timer1.startPeriodic(mDesiredSleepSchedule);
    //Clear the log on start up for DEBUG only
    if (call LogWrite.erase() != SUCCESS) {
		//printf("Boot.booted(): LogWrite.erase Failed\n");
		//printfflush();
    }
    mLocalProbePkt.probe = 1;
    mLocalProbePkt.dstNodeID = 0;
    mLocalProbePkt.srcNodeID = TOS_NODE_ID;
  }
  
    /**
   * To go to sleep, turn off AMControl
   */
  void GoToSleep()
  {
  	mModuleSleeping = TRUE;
  	call EnergyHarvesterDiscrete.clr();
  	call AMControl.stop();
    printf("\n\n");
    printfflush();
  }
  /**
   * When we wake up, turn on AMControl
   */
  void WakeUp()
  {
  	mProbesSent = 0; /* Have sent mProbesSent probe requests */
    mRCVWindow = FALSE; /* Have not completed a RECEIVE_PERIOD timer yet in this Radio-ON cycle */
    mModuleSleeping = FALSE;
  	call EnergyHarvesterDiscrete.set();
  	call AMControl.start();	
    dstNodeID = 0;
  }
  
  /** 
   * The primary purpose of Timer 0 is to kick off a temperature read and log storage
   */
  event void Timer0.fired()
  {
  	/* Read the battery voltage so the next time we come here we can determine
	 * if we need to change the time of timer1 firing
	 */
	call BatteryVoltage.read(); 
	 
  	if( state == IDLE && !mSendBusy )
  	{
  		//printf("Timer0 Fired, logging temperature\n");
        //printfflush();
  
	   	if(!mLogBusy)
	  	{		  	
			/* Take a temperature reading */
			if( call TemperatureReading.read() != SUCCESS)
			{
				printf("Timer0.fired(): Reading temperature failed\n");    
				printfflush();		
			}else{
				//printf("Timer0.fired():Reading temperature succeeded\n");
				//printfflush();
			}        
		}     	
	}
  }
  
  /***************************************************/
  /*  Flash Logger */
	
    event void LogRead.readDone(void* buf, storage_len_t len, error_t err) 
    {
    	//Check to see if the packet read is the right size
        if ( (len == sizeof(flashLogEntry_t)) && (buf == &mLocalLogEntry) )
        {
        	//We've read the log correctly, now send the packet
			//printf("LogRead.readDone:Trying to send a packet\n");
			//printfflush();
			atomic { mLogBusy = FALSE; }
			//If the radio isn't busy, send all entries in the log
			if( !radioBusy)
	    	{   
                flashLogEntry_t* lPacket ;
                lPacket = (flashLogEntry_t*)call Packet.getPayload(&pkt, sizeof (flashLogEntry_t));						    		
	            mLocalLogEntry.dstNodeID = dstNodeID;
                *lPacket = mLocalLogEntry;
                if (call AMSend.send(AM_BROADCAST_ADDR, &pkt, sizeof(flashLogEntry_t)) == SUCCESS) {
				  radioBusy = TRUE;
				  //printf("LogRead.readDone:AMSending succeeded.  Radio is busy\n");
				  //printfflush();
				}else{
					radioBusy = FALSE;
					printf("LogRead.readDone:AMSend failed\n");
					printfflush();
				}
				
			}else{
				printf("LogRead.readDone: Radio is busy\n");
				printfflush();
			}
    	}else{
    		printf("LogRead.readDone: buf did not match\n");
    		printfflush();
            mSendBusy = FALSE;
		}    	

	}
	
	event void LogWrite.eraseDone(error_t err) 
	{
	}
	event void LogWrite.appendDone(void* buf, storage_len_t len, 
                                 bool recordsLost, error_t err) 
    {
		atomic {mLogBusy = FALSE; }
		mRemoteBufferedEntriesIndex--;
        if(mRemoteBufferedEntriesIndex >= 0 ) {
        	mRemoteEntry = mRemoteBufferedEntries[mRemoteBufferedEntriesIndex];
			atomic {mLogBusy = TRUE; }
			if (call LogWrite.append(&mRemoteEntry, sizeof(flashLogEntry_t)) != SUCCESS) {
				atomic {mLogBusy = FALSE;}
				printf("LogWrite.appendDone():Packet write failed\n");
				printfflush();
			}else{
				packetCountWritten++;  //Increase the number of packets written
			}
		}
        else {
		  mRemoteBufferedEntriesIndex = 0;
        }
	}

 	event void LogRead.seekDone(error_t err) 
 	{
 	}

  	event void LogWrite.syncDone(error_t err) 
  	{
  	}
	
  /**************************************************/
  
  /***** Sensor Reading  ***********************/
  /**
   * After reading the sensor, we want to store this information to the log
   */
  event void TemperatureReading.readDone(error_t result, uint16_t data) {
    if (result != SUCCESS)
	{
  		/* Set the data to garbage because it wasn't right anyway */
  		data = 0xffff;
	}	  	

	mLocalEntry.timeStamp = call Timer0.getNow();
	mLocalEntry.temperature = data;  		
    mLocalEntry.voltage = mLastVoltageRead;   	

	mLocalEntry.srcNodeID = TOS_NODE_ID;
	mLocalEntry.sentStatus = 0;
    mLocalEntry.hopCount = MAX_HOP_COUNT;
    mLocalEntry.probe = 0;
	//printf("Node ID: %d,  Temperature: %u\n", TOS_NODE_ID, data);	
	//printfflush();
	if( mLogBusy == FALSE)
	{
		/* Write data to log */
	  	atomic {mLogBusy = TRUE;}		
		if (call LogWrite.append(&mLocalEntry, sizeof(flashLogEntry_t)) != SUCCESS) {
			atomic {mLogBusy = FALSE;}
			printf("TemperatureReading.readDone():Packet write failed\n");
			printfflush();
		}else{
			packetCountWritten++;  //Increase the number of packets written
			//printf("TemperatureReading.readDone():Packet Written Count: %d\n", packetCountWritten);
			//printfflush();
		}
	}
	
  }		
 
 
 /****** Sensor Reading End ************************/
 /****** AMC Start *********************************/
 
  task void sendProbe() {
  // TODO Try to get into SEND mode here, if possible, try to send PROBE packets
	if(state == IDLE && radioBusy == FALSE && packetCountWritten > 0) {
				
		//TODO send PROBE packet
		flashLogEntry_t *lPacket= (flashLogEntry_t*)call Packet.getPayload(&pkt, sizeof (flashLogEntry_t));
		*lPacket = mLocalProbePkt;
		//printf("** Setting mSendBusy = TRUE1\n");
		mSendBusy = TRUE;
		//printfflush();

		if (call AMSend.send(AM_BROADCAST_ADDR, &pkt, sizeof(flashLogEntry_t)) == SUCCESS) {
		  radioBusy = TRUE;
		  printf("sendProbe: %d sent probe packet\n", mLocalProbePkt.srcNodeID);
		  printfflush();
		  mProbesSent++;
		}else{
			//radioBusy = FALSE;
			printf("sendProbe: srcNodeID = %d sending probe failed\n", mLocalProbePkt.srcNodeID);
			printfflush();
			//printf("** Setting mSendBusy = FALSE0\n");
			//mSendBusy = FALSE;
			//printfflush();
		}
	}
  }
 
  event void AMControl.startDone(error_t err) {
  	
    //printf("AMCControl Start Done\n");
    //printfflush();
    if (err == SUCCESS) {
        printf("Starting WaitTimer with period %d\n",TOS_NODE_ID*200);
        printfflush();
        call WaitTimer.startOneShot(TOS_NODE_ID*200);
    }
    else {
      call AMControl.start();      
    }
  }
  
  event void WaitTimer.fired() {
     printf("WaitTimer.fired: posting sendProbe\n");
     printfflush();
     post sendProbe(); 
  }
  
  event void AMControl.stopDone(error_t err) {
  }
	
 /**
  * This is in control of sending all the stored log files 
  */
  event void Timer1.fired() {  	
 	static uint32_t Timer1CurrentPeriod = SHORT_SLEEP_SCHEDULE_MILI;
 	static uint32_t Timer1CurrentScheduleTicks = 0;
 	
 	//printf("I just woke up with sleep schedule %lu\n", Timer1CurrentPeriod);
 	//printfflush();
 	//To synch up, we need to know how many times we've executed this sleep schedule
 	Timer1CurrentScheduleTicks++;
 	printf("CurrentTick: %lu   Current Schedule:  %lu\n", Timer1CurrentScheduleTicks, Timer1CurrentPeriod );
 	printfflush();
 	
 	if( sychnronizeSleepSchedule == TRUE)
 	{
 		//printf("sychnronizeSleepSchedule is true.  Setting sleep schedule to %lu\n", mDesiredSleepSchedule );
 		sychnronizeSleepSchedule = FALSE;
 		Timer1CurrentScheduleTicks = 0;
 		Timer1CurrentPeriod = mDesiredSleepSchedule;
		call Timer1.startPeriodic(Timer1CurrentPeriod);	
 	}else if ( Timer1CurrentPeriod != mDesiredSleepSchedule )
	{		
		if (  Timer1CurrentPeriod > mDesiredSleepSchedule )
		{
			Timer1CurrentScheduleTicks = 0;
			Timer1CurrentPeriod = mDesiredSleepSchedule;
			call Timer1.startPeriodic(Timer1CurrentPeriod);	
		}else{
			//printf("Current (%lu) < Desired (%lu)\n", Timer1CurrentPeriod, mDesiredSleepSchedule);
			Timer1CurrentPeriod = mDesiredSleepSchedule - Timer1CurrentPeriod * ( Timer1CurrentScheduleTicks % (mDesiredSleepSchedule/Timer1CurrentPeriod));
			//printf("New calculated current:  %lu\n", Timer1CurrentPeriod);
			//printfflush();
			call Timer1.startOneShot(Timer1CurrentPeriod); 	
			sychnronizeSleepSchedule = TRUE;
		}	
	}
	/* Turn the radio back on */
    WakeUp();
    
  	if( packetSentCount == 0)
  	{
  		mSendPacketsStartTime = call LocalTime.get();
  	}
  }
  
  event void AMSend.sendDone(message_t* msg, error_t error) {
    if (&pkt == msg && error == SUCCESS) {
      	radioBusy = FALSE;
        
        //TODO If the packet which was just sent was a probe request or response packet, then dont do anything more
        if(state == IDLE  ) // this could have only happened if the packet just sent was a PROBE request 
        {
            printf("sent Probe Request\n");
            printfflush(); 
            mSendBusy = FALSE;
            call ProbeTimer.stop();
            call ProbeTimer.startOneShot(PROBE_STEP_PERIOD);

        }else if( state == RECEIVE)
        {
        	printf("sent Probe Response\n");
            printfflush(); 
            mSendBusy = FALSE;
        	
        }
        else { 
			packetSentCount++;
			if( packetSentCount == packetCountWritten)
			{			
				mSendPacketsEndTime = call LocalTime.get();
				//printf("AMSend.sendDone(): Time to send %d log entries: %u\n",packetSentCount, (mSendPacketsEndTime - mSendPacketsStartTime));
				totalPacketSentCount += packetSentCount;
				printf("Sent - %d\n",totalPacketSentCount);
				printfflush();
				mSendPacketsEndTime = 0;
				mSendPacketsStartTime = 0;
				packetSentCount = 0;
				packetCountWritten = 0;		
				mSendBusy = FALSE;
				//printf("** Setting mSendBusy = FALSE2\n");
				//printfflush();
				state = IDLE;
                //We're done sending once in this radio cycle
                // Now we wait for LONG_RECEIVE_PERIOD before going to sleep.
				// This will give us enough time for the other node to send us probe packets
                if(mRCVWindow == FALSE) 
				{
                  call ReceiveTimer.startOneShot(LONG_RECEIVE_PERIOD);
				}
                else 
				{
                  GoToSleep(); //We're done sending and receiving
				}

			}else{
				atomic {mLogBusy = FALSE;}
				//If there are more packets to send, do another log read to initiate another send
				if (call LogRead.read(&mLocalLogEntry, sizeof(flashLogEntry_t)) != SUCCESS) 
				{
					// Handle error.
					//printf("AMSend.sendDone(): Load Read Error\n");
					//printfflush();
				}else{
					//printf("AMSend.sendDone(): Load Read success\n");
					//printfflush();
				}
			}
        }
    }else{
    	
	}

    
  }

  task void doLogRead() {
  	  printf("Waiting for mLogBusy == true\n");
  	  printfflush();
      if(mLogBusy==TRUE)
      {
      	post doLogRead();      	
      }else{   
	      if (call LogRead.read(&mLocalLogEntry, sizeof(flashLogEntry_t)) != SUCCESS) 
	      {
			atomic { mSendBusy = FALSE;}
			printf("** Setting mSendBusy = FALSE3 with mlogBusy = %d\n", mLogBusy);
			printfflush();
			// Handle error.
			printf("Receive.receive() LogRead Error\n");
			printfflush();
	      }else{
				//printf("Receive.receive() LogRead success\n");
				//printfflush();
		  }
	  }
}

  event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) {

	  flashLogEntry_t* btrpkt = (flashLogEntry_t*)payload;
  	  //printf("Received Packet\n");
      //printfflush();
      if (len == sizeof(flashLogEntry_t)) {	
	      // TODO If received probe response to my probe request in IDLE state, then try to do a LogRead, change state to SEND
	      if(btrpkt->probe == 1 && btrpkt->srcNodeID == TOS_NODE_ID && state == IDLE ) {
	      	//Kill the ReceiveTimer
	        call ReceiveTimer.stop();	
            //Kill the ProbeTimer
            call ProbeTimer.stop();
            mProbesSent = MAX_PROBES;
	        //TODO LogRead
	        printf("Received probe response from %d to my request, going into send mode\n", btrpkt->dstNodeID);
            dstNodeID = btrpkt->dstNodeID;
	        printfflush();
	        state = SEND;
	        //mLogBusy = FALSE;
	        post doLogRead();
	     }
	     // TODO If received Probe request packet, and I am in IDLE mode, then respond to Probe packet and move to RECEIVE mode and start RECEIVE mode timer
	     else if(btrpkt->probe ==1 && btrpkt->srcNodeID != TOS_NODE_ID && state == IDLE) {
             call ProbeTimer.stop();
             call WaitTimer.stop();
	     	 state = RECEIVE;
	         //TODO Send response to Probe request packet
	         printf("Received probe request from srcNodeID = %d, going into receive mode\n",btrpkt->srcNodeID);
	         printfflush();
	
	         if( !radioBusy)
			 {    		
			 	//Send packet back as response to probe request
				flashLogEntry_t* lPacket = (flashLogEntry_t*)call Packet.getPayload(&pkt, sizeof (flashLogEntry_t));
				*lPacket = *btrpkt;
                lPacket->dstNodeID=TOS_NODE_ID;
				if (call AMSend.send(AM_BROADCAST_ADDR, &pkt, sizeof(flashLogEntry_t)) == SUCCESS) {
				  radioBusy = TRUE;				  
				}else{
					radioBusy = FALSE;
					printf("Receive.Receive: AMSend failed\n");
					printfflush();
				}
			 }else{
				printf("Receive.receive: Radio is busy\n");
				printfflush();
			 } 	         
			 mRemoteBufferedEntriesIndex = 0;
	         call ReceiveTimer.startOneShot(RECEIVE_PERIOD);
	     }else if(btrpkt->probe ==1 && btrpkt->srcNodeID != TOS_NODE_ID && state == RECEIVE ){
	     	printf("Received probe request from srcNodeID = %d while I'm busy receiving\n", btrpkt->srcNodeID);
	     	printfflush();	     	
	     }
	      // We will receive and log packets only if we are in the RECEIVE mode
	      else if(state == RECEIVE){
	      	//printf("Received packet...\n");
	      	//printfflush();
	        if(btrpkt->srcNodeID == TOS_NODE_ID) {
                //I am receiving my own packets
                printf("Ignoring a packet\n"); printfflush();
	            return msg;
	        }
	        //printf("Current mRemoteBufferedEntriesIndex: %d\n", mRemoteBufferedEntriesIndex);
	        //printfflush();
	        //Update 'totals', assumes node IDs are 0 through 3
	        atomic {packetReceivedCount[btrpkt->srcNodeID]++;}
	        //TODO LogWrite this packet
	        btrpkt->hopCount--;
	        if(btrpkt->hopCount > 0 ) {
	            //In the RECEIVE mode, dont log anything, append everything to the mRemoteBufferedEntries array
	            if(mRemoteBufferedEntriesIndex < MAX_BUFFERED_ENTRIES) {
                    mRemoteBufferedEntries[mRemoteBufferedEntriesIndex]=*btrpkt;
    	            mRemoteBufferedEntriesIndex++;
                }
	        }
          }
	}
	return msg;
  }

  event void ReceiveTimer.fired() {
      printf("ReceiveTimer.fired - packetCountReceived = %d,%d,%d,%d \n", packetReceivedCount[0], packetReceivedCount[1], packetReceivedCount[2], packetReceivedCount[3]);
      printfflush();
      state = IDLE;
      mRCVWindow = TRUE;
      if(mProbesSent < MAX_PROBES) { // We may still have probes to send out
          post sendProbe();
          call ProbeTimer.startOneShot(PROBE_STEP_PERIOD);
      }
      else {
          GoToSleep(); // We're done sending probes and done receiving
          // in this radio cycle
      }
      //Log all Entries here
      if(mRemoteBufferedEntriesIndex > 0 ) {
          mRemoteBufferedEntriesIndex--;
          mRemoteEntry = mRemoteBufferedEntries[mRemoteBufferedEntriesIndex];         
		  atomic{ mLogBusy = TRUE;}
		if (call LogWrite.append(&mRemoteEntry, sizeof(flashLogEntry_t)) != SUCCESS) {
			atomic {mLogBusy = FALSE;}
			printf("ReceiveTimer.fired():Packet write failed\n");
			printfflush();
		}else{
			packetCountWritten++;  //Increase the number of packets written
			//printf("ReceiveTimer.fired():Packet Written Count: %d\n", packetCountWritten);
			//printfflush();
		}
    }      
  }
  event void ProbeTimer.fired() {
     if(mProbesSent <= MAX_PROBES) post sendProbe(); 
     else if(mRCVWindow == FALSE) call ReceiveTimer.startOneShot(RECEIVE_PERIOD);
     else GoToSleep();// We're done sending probes and done receiving
  }
}
